namespace Sustainalytics.ESGComputing.Service.Filters
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;

    using Sustainalytics.ESGComputing.Service.Exceptions;
    using Sustainalytics.ESGComputing.Service.Extensions;
    using Sustainalytics.ESGComputing.Service.Helpers;
    using Sustainalytics.ESGRatings.BusinessLogic.Computing.Exceptions;
    using Sustainalytics.ESGRatings.DataContract;
    using Serilog;

    public sealed class CustomExceptionFilterAttribute : ExceptionFilterAttribute
    {
        private readonly IDictionary<Type, Tuple<HttpStatusCode, ErrorCodes>> _registeredExceptions =
            new Dictionary<Type, Tuple<HttpStatusCode, ErrorCodes>>()
                {
                    { typeof(UnknownSetException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.UnknownSet) },
                    { typeof(EmptySetListException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.UnknownSet) },
                    { typeof(UnknownUniverseException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.UnknownUniverse) },
                    { typeof(UnknownMatrixException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.UnknownMatrix) },
                    { typeof(UnknownCompanyException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.UnknownCompany) },
                    { typeof(ComputeException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.InternalServerError, ErrorCodes.InternalComputationError) },
                    { typeof(UnknownTheme), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.InvalidInput) },
                    { typeof(InvalidInput), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.InvalidInput) },
                    { typeof(DuplicateEntityException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.InvalidInput) },
                    { typeof(UnknownIndicatorException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.InvalidInput) },
                    { typeof(InvalidSetException), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.InvalidInput) },
                    { typeof(ESGEntityNotFound), new Tuple<HttpStatusCode, ErrorCodes>(HttpStatusCode.BadRequest, ErrorCodes.InvalidInput) },
                };

        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            Tuple<HttpStatusCode, ErrorCodes> information;
            var exception = actionExecutedContext.Exception;
            var exceptionType = exception.GetType();

            if (exceptionType == typeof(AggregateException))
                exception = exception.InnerException;


            if (this._registeredExceptions.TryGetValue(exception.GetType(), out information))
            {
                actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(
                   information.Item1,
                   new ErrorModel { ErrorStatusCode = (int)information.Item2, ErrorMessage = exception.Message });
            }

            actionExecutedContext.SetErrorResponseFor<Exception>(HttpStatusCode.InternalServerError, exception.ToString());

            Log.Error(exception, "");
        }
    }
}